package com.codi.bus.core.service.impl;

import com.codi.base.util.DateUtils;
import com.codi.bus.constant.GlobalConstant;
import com.codi.bus.core.dao.*;
import com.codi.bus.core.domain.*;
import com.codi.bus.core.service.FundDetailService;
import com.codi.fundData.vo.FundChargeRateVo;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @Author: zengxl
 * @Description:
 * @Date: 2018/5/21 14:56
 */
@Service
public class BusinessIncomeService {
    @Autowired
    private CdChargerateDao cdChargerateDao;
    @Autowired
    private CdBusinessIncomeDao cdBusinessIncomeDao;
    @Autowired
    private CdBusinessIncomeErrorlogDao cdBusinessIncomeErrorlogDaoDao;
    @Autowired
    private ProfitDao profitDao;
    @Autowired
    private TradeOrdersDao tradeOrdersDao;

    @Resource(name = "fundDetailService")
    private FundDetailService fundDetailService;

    @Transactional
    public void exec(){
        List<FundChargeRateVo> fundChargeRateVoList = fundDetailService.getFundChargeRate();
        List<CdChargerate> cdChargerateList = cdChargerateDao.selectAllChargerate();
        //客户维护费分成比例
        Map<Long,CdChargerate> fcblMap= Maps.newHashMap();
        for(CdChargerate cdChargerate:cdChargerateList){
            fcblMap.put(cdChargerate.getInvestAdvisorCode(),cdChargerate);
        }
        //基金费率：管理费、营销费
        Map<String,FundChargeRateVo> flMap= Maps.newHashMap();
        for(FundChargeRateVo vo:fundChargeRateVoList){
            if(fcblMap.containsKey(vo.getInvestAdvisorCode())){
                flMap.put(vo.getMainCode(),vo);
            }
        }
        Date date = new Date();
        BigDecimal year = new BigDecimal(365);
        Date currentDate = DateUtils.addDay(date, -1);
        TradeOrders queryVo = new TradeOrders();

        String dateTime = DateUtils.getFormatedDate(currentDate,"yyyyMMdd");
        queryVo.setLastupdateTime(dateTime);
        List<TradeOrders> tradeOrderUpdateList = tradeOrdersDao.selectByUpdateTime(queryVo);
        for(TradeOrders order:tradeOrderUpdateList){
            if(!"1".equals(order.getTaconfirmFlag())){
                continue;
            }
            if( order.getTaFare() != null && order.getTaFare().doubleValue() > 0 ){
                if(GlobalConstant.FUND_BUSIN_CODE_APPLY_BUY.equals(order.getFundBusinCode()) || GlobalConstant.FUND_BUSIN_CODE_APPLY_RBUY.equals(order.getFundBusinCode())){
                    //认/申购费
                    saveIncome(Long.valueOf(order.getUserId()),order.getClientId(),order.getFundCode(),currentDate,order.getTaFare(),1);
                }else if(GlobalConstant.FUND_BUSIN_CODE_APPLY_SELL.equals(order.getFundBusinCode())){
                    //3. 赎回费
                    saveIncome(Long.valueOf(order.getUserId()),order.getClientId(),order.getFundCode(),currentDate,order.getTaFare(),3);
                }
            }
            String deductStatus = order.getDeductStatus();
            if(StringUtils.isBlank(deductStatus) ){
                continue;
            }
            BigDecimal balance = order.getBalance();
            if(balance == null || balance.longValue() <=0){
                continue;
            }
            if(GlobalConstant.FUND_BUSIN_CODE_APPLY_BUY.equals(order.getFundBusinCode())
                || GlobalConstant.FUND_BUSIN_CODE_APPLY_RBUY.equals(order.getFundBusinCode())
                || GlobalConstant.FUND_BUSIN_CODE_APPLY_FIX_BUY.equals(order.getFundBusinCode())){

                String fundCode = order.getFundCode();
                FundChargeRateVo vo = flMap.get(fundCode);
                if(vo == null || StringUtils.isBlank(vo.getFundType())){
                    saveErrorIncome(Long.valueOf(order.getUserId()),order.getClientId(),fundCode,currentDate,order.getBalance(),5,"该基金从聚源获取不到管理费、营销费信息");
                    continue;
                }
                boolean isHbFund = false;
                if(GlobalConstant.FUND_TYPE_CURRENCY_STR.equals(vo.getFundType())){
                    isHbFund = true;
                }
                long tt = balance.longValue();
                //支付方式费用
                String capitalMode = order.getCapitalMode();
                if("I".equals(capitalMode)){
                    if(isHbFund){
                        BigDecimal resultT = null;
                        if(tt<50000){
                            resultT = new BigDecimal(2);
                        }else if(tt >=50000 && tt <100000){
                            resultT = new BigDecimal(5);
                        }else if(tt>=100000){
                            resultT = new BigDecimal(10);
                        }
                        saveIncome(Long.valueOf(order.getUserId()),order.getClientId(),order.getFundCode(),currentDate,resultT,5);
                    }else {
                        BigDecimal resultT = balance.multiply(new BigDecimal(0.0023)).divide(year,4, RoundingMode.HALF_DOWN);
                        if(resultT.longValue()<2){
                            resultT = new BigDecimal(2);
                        }
                        saveIncome(Long.valueOf(order.getUserId()),order.getClientId(),order.getFundCode(),currentDate,resultT,5);
                    }
                }

                //浦发监管费
                BigDecimal jgf = null;
                if(isHbFund){
                    jgf = balance.multiply(new BigDecimal(0.0001));
                }else{
                    //恒生系统服务费--非货币
                    BigDecimal resultT = null;
                    if(tt <= 5000000000L){
                        resultT = balance.multiply(new BigDecimal(0.0006));
                    }else if(tt > 5000000000L && tt <= 20000000000L){
                        resultT = balance.multiply(new BigDecimal(0.0004));
                    }else if(tt > 20000000000L){
                        resultT = balance.multiply(new BigDecimal(0.0002));
                    }
                    saveIncome(Long.valueOf(order.getUserId()),order.getClientId(),order.getFundCode(),currentDate,resultT,8);

                    if(GlobalConstant.FUND_TYPE_BOND_STR.equals(vo.getFundType())){
                        jgf = balance.multiply(new BigDecimal(0.0002));
                    }else{
                        jgf = balance.multiply(new BigDecimal(0.0005));
                    }
                }
                saveIncome(Long.valueOf(order.getUserId()),order.getClientId(),order.getFundCode(),currentDate,jgf,6);



            }

        }
        BigDecimal allShares = new BigDecimal(0);
        List<Profit> profitList = profitDao.selectZc(DateUtils.getFormatedDate(currentDate,"yyyy-MM-dd"));
        for(Profit profit:profitList){
            if(profit.getShares() == null){
                continue;
            }
            BigDecimal shares = profit.getShares();
            String fundCode = profit.getFundCode();
            FundChargeRateVo vo = flMap.get(fundCode);
            if(vo == null || StringUtils.isBlank(vo.getFundType())){
                saveErrorIncome(Long.valueOf(profit.getUserId()),profit.getClientId(),fundCode,currentDate,shares,2,"该基金从聚源获取不到管理费、营销费信息");
                continue;
            }
            boolean isHbFund = false;
            if(GlobalConstant.FUND_TYPE_CURRENCY_STR.equals(vo.getFundType())){
                isHbFund = true;
                allShares.add(shares);
            }
            Long investAdvisorCode = vo.getInvestAdvisorCode();
            CdChargerate chargerate = fcblMap.get(investAdvisorCode);
            if(chargerate == null){
                saveErrorIncome(Long.valueOf(profit.getUserId()),profit.getClientId(),fundCode,currentDate,shares,2,"该基金公司未配置维护费分成比例,对应基金公司:"+vo.getInvestAdvisorName()+",基金公司代码:"+vo.getInvestAdvisorCode());
                continue;
            }
            //管理费
            String glf = vo.getGlf();
            if(StringUtils.isBlank(glf)){
                saveErrorIncome(Long.valueOf(profit.getUserId()),profit.getClientId(),fundCode,currentDate,shares,2,"该基金公司未配置管理费,对应基金公司:"+vo.getInvestAdvisorName()+",基金公司代码:"+vo.getInvestAdvisorCode());
                continue;
            }
            Double glfNum = null;
            try {
                glfNum = Double.valueOf(glf.replace("%",""));
            } catch (NumberFormatException e) {
                saveErrorIncome(Long.valueOf(profit.getUserId()),profit.getClientId(),fundCode,currentDate,shares,2,"该基金公司配置管理费数据转换错误,对应基金公司:"+vo.getInvestAdvisorName()+",基金公司代码:"+vo.getInvestAdvisorCode()+",管理费:"+glf);
                continue;
            }


            String fcbl = null;
            if(isHbFund){
                fcbl = chargerate.getChargeRateHb();
            }else {
                fcbl = chargerate.getChargeRateFhb();
            }
            if(StringUtils.isBlank(fcbl)){
                saveErrorIncome(Long.valueOf(profit.getUserId()),profit.getClientId(),fundCode,currentDate,shares,2,"未配置分成比例,对应基金公司:"+vo.getInvestAdvisorName()+",基金公司代码:"+vo.getInvestAdvisorCode()+",是否货币基金:"+isHbFund);
                continue;
            }
            Double fcblNum = null;
            try {
                fcblNum = Double.valueOf(fcbl.replace("%",""));
            } catch (NumberFormatException e) {
                saveErrorIncome(Long.valueOf(profit.getUserId()),profit.getClientId(),fundCode,currentDate,shares,2,"该基金公司配置分成比例[服务费]数据转换错误,对应基金公司:"+vo.getInvestAdvisorName()+",基金公司代码:"+vo.getInvestAdvisorCode()+",分成比例:"+fcbl);
                continue;
            }
            //客户维护费
            BigDecimal result = shares.multiply(new BigDecimal(glfNum/100)).multiply(new BigDecimal(fcblNum/100)).divide(year,4, RoundingMode.HALF_DOWN);
            saveIncome(Long.valueOf(profit.getUserId()),profit.getClientId(),profit.getFundCode(),currentDate,result,2);

            //营销费
            String yxf = vo.getYxf();
            if(!StringUtils.isBlank(yxf)){
                Double yxfNum = null;
                try {
                    yxfNum = Double.valueOf(yxf.replace("%",""));
                } catch (NumberFormatException e) {
                    saveErrorIncome(Long.valueOf(profit.getUserId()),profit.getClientId(),fundCode,currentDate,shares,4,"该基金公司配置分成比例[营销费]数据转换错误,对应基金公司:"+vo.getInvestAdvisorName()+",基金公司代码:"+vo.getInvestAdvisorCode()+",分成比例:"+yxf);
                    continue;
                }
                BigDecimal yxfResult = shares.multiply(new BigDecimal(yxfNum/100)).divide(year,4, RoundingMode.HALF_DOWN);
                saveIncome(Long.valueOf(profit.getUserId()),profit.getClientId(),profit.getFundCode(),currentDate,yxfResult,4);
            }
        }
        long temp = allShares.longValue();
        BigDecimal result = null;
        if(temp <= 5000000000L){
            result = allShares.multiply(new BigDecimal(0.0002)).divide(year,4, RoundingMode.HALF_DOWN);
        }else if(temp > 5000000000L && temp <= 20000000000L){
            result = allShares.multiply(new BigDecimal(0.00015)).divide(year,4, RoundingMode.HALF_DOWN);
        }else if(temp > 20000000000L){
            result = allShares.multiply(new BigDecimal(0.0001)).divide(year,4, RoundingMode.HALF_DOWN);
        }
        ////恒生系统服务费--货币--需要分摊至每一个持有货币基金的用户
        for(Profit profit:profitList){
            if(profit.getShares() == null){
                continue;
            }
            BigDecimal shares = profit.getShares();
            String fundCode = profit.getFundCode();
            FundChargeRateVo vo = flMap.get(fundCode);
            if(vo == null || StringUtils.isBlank(vo.getFundType())){
                continue;
            }
            if(GlobalConstant.FUND_TYPE_CURRENCY_STR.equals(vo.getFundType()) && allShares.longValue() > 0){
                BigDecimal multiply = result.divide(allShares,4, RoundingMode.HALF_DOWN).multiply(shares);
                saveIncome(Long.valueOf(profit.getUserId()),profit.getClientId(),profit.getFundCode(),currentDate,multiply,7);
            }
        }
    }

    private void saveIncome(long userId,String clientId,String fundCode,Date dataTime,BigDecimal result,int type){
        CdBusinessIncome income = new CdBusinessIncome();
        income.setUserId(userId);
        income.setClientId(clientId);
        income.setFundCode(fundCode);
        income.setFareDatetime(dataTime);
        income.setFareNum(result);
        income.setFareType(type);
        income.setCreateTime(new Date());
        cdBusinessIncomeDao.insert(income);
    }
    private void saveErrorIncome(long userId,String clientId,String fundCode,Date dataTime,BigDecimal result,int type,String errorMsg){
        CdBusinessIncomeErrorlog log = new CdBusinessIncomeErrorlog();
        log.setUserId(userId);
        log.setClientId(clientId);
        log.setFundCode(fundCode);
        log.setFareDatetime(dataTime);
        log.setFareNum(result);
        log.setFareType(type);
        log.setErrorLog(errorMsg);
        log.setCreateTime(new Date());
        cdBusinessIncomeErrorlogDaoDao.insert(log);
    }
}
